// Implementation of the test mdoel
// Copyright 2004 (C) Ralph Thomas

#include <model/test/testModel.h>
#include <model/attributeInfo.h>
#include <model/attributeNames.h>
#include <model/collection.h>
#include <adobe/array.hpp>

namespace model {
	testModel::testModel( const url* theUrl ) :
	 _theUrl( NULL ), _refCount( 1 ), _foo( 'a' ), _processing( false ) {
		if( !theUrl ) return;
		_theUrl = url::fromUrl( theUrl );
	}

	testModel::~testModel() {
		toolkit::application::getInstance().removeIdle( this );
		if( _theUrl ) delete _theUrl;
	}

	bool testModel::init() {
		_children.push_back( adobe::value_t( _theUrl->getCompleteUrl() + "/1" ) );
		_children.push_back( adobe::value_t( _theUrl->getCompleteUrl() + "/foo" ) );
		_children.push_back( adobe::value_t( _theUrl->getCompleteUrl() + "/bar" ) );
		toolkit::application::getInstance().addIdle( this, 100 );
		if( _theUrl ) return true;
		return false;
	}

	model* testModel::retain() const {
		testModel* us = const_cast<testModel*>( this );
		us->_refCount++;
		return us;
	}

	void testModel::release() {
		_refCount--;
		if( (_refCount == 0) && !_processing ) delete this;
	}

	void testModel::subscribe( receiver* r ) {
		_receivers.subscribe( r );
	}

	void testModel::unsubscribe( const receiver* r ) {
		_receivers.unsubscribe( r );
	}

	adobe::value_t testModel::getAttribute( const std::string& attrName ) const {
		if( attrName == kModelValid ) {
			return adobe::value_t( true );
		} else if( attrName == kModelAttributes ) {
			attributeInfo ai;
			ai.addAttribute( kModelValid, false );
			ai.addAttribute( kModelAttributes, false );
			ai.addAttribute( kChildren, false );
			ai.addAttribute( kName, false );
			ai.addAttribute( kType, false );
			ai.addAttribute( kParent, false );
			return adobe::value_t( ai );
		} else if( attrName == kChildren ) {
			return adobe::value_t( _children );
		} else if( attrName == kName ) {
			return adobe::value_t( _theUrl->getPath() );
		} else if( attrName == kType ) {
			return adobe::value_t( util::string(
				"x-mission-test/foo" ) );
		} else if( attrName == kData ) {
			util::string data;
			data = "this is just some\r\ndata coming all the way\r\nfrom the model known to the world as\r\n";
			data += _theUrl->getCompleteUrl();
			data += "\r\nand have a nice day!";
			return adobe::value_t( data );
		} else if( attrName == kParent ) {
			util::string parent = _theUrl->getPath();
			unsigned int sl = parent.rfind( '/' );
			if( sl == (unsigned int) -1 )
				return adobe::value_t( util::string( "" ) );
			//
			// The parent has the path without whatever came after
			// the slash we found (or the slash we found).
			//
			parent = parent.substr( 0, sl );
			util::string pUrl =
				_theUrl->getUrlWithoutParts( url::kPath );
			pUrl += '/' + parent;
			return adobe::value_t( pUrl );
		}
		return adobe::value_t();
	}

	void testModel::setAttribute( const std::string& attrName,
		const adobe::value_t& a ) {}
	adobe::value_t testModel::execute( const std::string& action,
		const adobe::value_t& param ) {
		return adobe::value_t( false );
	}
	void testModel::process() {
		//
		// We don't make more children past 'z' (and we don't
		// repeat, as that breaks the rules).
		//
		if( _foo > 'z' ) return;
		//
		// Make our child URL, and add it to the list of children.
		//
		util::string child = _theUrl->getCompleteUrl() + "/";
		child += _foo; _foo++;
		_children.push_back( adobe::value_t( child ) );
		//
		// We don't want to be deleted while this is going on.
		//
		_processing = true;
		_receivers.notify( this, kChildren );
		_processing = false;
		if( _refCount == 0 ) delete this;
	}
};

